﻿using System.ComponentModel;
using System.Globalization;

namespace Ulid;

/// <summary>
/// 将 <see cref="string"/> 类型或 <see cref="T:byte[]"/> 类型转换为 <see cref="Ulid"/> 类型，反之亦然。
/// </summary>
public sealed class UlidTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
        => sourceType == null
            ? throw new ArgumentNullException(nameof(sourceType))
            : sourceType == typeof(byte[])
            || sourceType == typeof(string)
            || base.CanConvertFrom(context, sourceType);

    public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
        => destinationType == typeof(byte[])
            || destinationType == typeof(string)
            || base.CanConvertTo(context, destinationType);

    public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
        => value is byte[] asByteArray
            ? new Ulid(asByteArray)
            : value is string asString
            ? Ulid.TryParse(asString, out var ulid) ? ulid : throw new NotSupportedException($"Invalid Ulid representation: \"{asString}\"")
            : base.ConvertFrom(context, culture, value);

    public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
        => destinationType == typeof(byte[])
            ? ((Ulid?)value)?.ToByteArray()
            : destinationType == typeof(string) ? ((Ulid?)value).ToString() : base.ConvertTo(context, culture, value, destinationType);
}
